--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / NomadNet.git / files / nomadnet / vendor / additional_urwid_widgets / widgets / indicative_listbox.py
Displaying Raw • Download
nomadnet/vendor/additional_urwid_widgets/widgets/indicative_listbox.py ace2969770ebded4cea2d6d23d9823c3641f0965 (ace29697) Text, 22.85 KB
T8b949e#! /usr/bin/env python3
T8b949e# -*- coding: utf-8 -*-
Tff7b72from T7ee787.T7ee787.T7ee787assisting_modulesT7ee787.T7ee787modifier_key Tff7b72import Te6edf3MODIFIER_KEY T8b949e# pylint: disable=unused-import
Tff7b72import T7ee787enum
Tff7b72import T7ee787random
Tff7b72import T7ee787urwid
Tff7b72class T56d364IndicativeListBoxTb4b4b4(Te6edf3urwidTff7b72.Td2a8ffWidgetWrapTb4b4b4)Tb4b4b4:
T8b949e"""Adds two bars to a 'urwid.ListBox', that make it obvious that due to limited space only a part of the list items is displayed."""
Te6edf3_TYPE_ERR_MSG Tff7b72= Ta5d6ff"Ta5d6fftype Tffd700{}Ta5d6ff was expected for Tffd700{}Ta5d6ff, but found: Tffd700{}Ta5d6ff.Ta5d6ff"
Te6edf3_VALUE_ERR_MSG Tff7b72= Ta5d6ff"Ta5d6ffunrecognized value: Tffd700{}Ta5d6ff.Ta5d6ff"
T8b949e# These values are translated by 'get_nearest_valid_position()' into the corresponding int values.
Tff7b72class T56d364POSITIONTb4b4b4(Te6edf3enumTff7b72.Td2a8ffEnumTb4b4b4)Tb4b4b4:
Te6edf3LAST Tff7b72= T79c0ff1
Te6edf3MIDDLE Tff7b72= T79c0ff2
Te6edf3RANDOM Tff7b72= T79c0ff3
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bodyTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3positionTff7b72=T79c0ff0Tb4b4b4, Te6edf3on_selection_changeTff7b72=Tff7b72NoneTb4b4b4, Te6edf3initialization_is_selection_changeTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3modifier_keyTff7b72=Te6edf3MODIFIER_KEYTff7b72.Td2a8ffNONETb4b4b4, Te6edf3return_unused_navigation_inputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3topBar_alignTff7b72=Ta5d6ff"Ta5d6ffcenterTa5d6ff"Tb4b4b4,
Te6edf3topBar_endCovered_propTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ff▲Ta5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4, Te6edf3topBar_endExposed_propTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ff───Ta5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4, Te6edf3bottomBar_alignTff7b72=Ta5d6ff"Ta5d6ffcenterTa5d6ff"Tb4b4b4,
Te6edf3bottomBar_endCovered_propTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ff▼Ta5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4, Te6edf3bottomBar_endExposed_propTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ff───Ta5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4, Te6edf3highlight_offFocusTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# If not already done, wrap each item of the body in an 'urwid.AttrMap'. This is necessary to enable off focus highlighting.
Te6edf3bodyTb4b4b4[Tb4b4b4:Tb4b4b4] Tff7b72= Tb4b4b4[Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4(Te6edf3itemTb4b4b4, Tff7b72NoneTb4b4b4) Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4) Tff7b72else Te6edf3item
Tff7b72for Te6edf3item Tff7b72in Te6edf3bodyTb4b4b4]
T8b949e# The body of the 'urwid.Frame' is a 'urwid.ListBox'.
Tff7b72selfTff7b72.Td2a8ff_listbox Tff7b72= Te6edf3urwidTff7b72.Td2a8ffListBoxTb4b4b4(Te6edf3bodyTb4b4b4)
T8b949e# Select the specified list position, or the nearest valid one.
Te6edf3nearest_valid_position Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_nearest_valid_positionTb4b4b4(Te6edf3positionTb4b4b4)
Tff7b72if Te6edf3nearest_valid_position Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffset_focusTb4b4b4(Te6edf3nearest_valid_positionTb4b4b4)
T8b949e# The bars are just 'urwid.Text' widgets.
Tff7b72selfTff7b72.Td2a8ff_top_bar Tff7b72= Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4(Te6edf3urwidTff7b72.Td2a8ffTextTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3alignTff7b72=Te6edf3topBar_alignTb4b4b4)Tb4b4b4,
Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_bottom_bar Tff7b72= Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4(Te6edf3urwidTff7b72.Td2a8ffTextTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3alignTff7b72=Te6edf3bottomBar_alignTb4b4b4)Tb4b4b4,
Tff7b72NoneTb4b4b4)
T8b949e# Wrap 'urwid.Frame'.
Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Te6edf3urwidTff7b72.Td2a8ffFrameTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_listboxTb4b4b4,
Te6edf3headerTff7b72=Tff7b72selfTff7b72.Td2a8ff_top_barTb4b4b4,
Te6edf3footerTff7b72=Tff7b72selfTff7b72.Td2a8ff_bottom_barTb4b4b4,
Te6edf3focus_partTff7b72=Ta5d6ff"Ta5d6ffbodyTa5d6ff"Tb4b4b4)Tb4b4b4)
T8b949e# During the initialization of 'urwid.AttrMap', the value can be passed as non-dict. After initializing, its value can be
T8b949e# manipulated by passing a dict. The dicts I create below will be used later to change the appearance of the bars.
Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_markup Tff7b72= Te6edf3topBar_endCovered_propTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_focus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3topBar_endCovered_propTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_offFocus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3topBar_endCovered_propTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_markup Tff7b72= Te6edf3topBar_endExposed_propTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_focus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3topBar_endExposed_propTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_offFocus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3topBar_endExposed_propTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_markup Tff7b72= Te6edf3bottomBar_endCovered_propTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_focus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3bottomBar_endCovered_propTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_offFocus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3bottomBar_endCovered_propTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_markup Tff7b72= Te6edf3bottomBar_endExposed_propTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_focus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3bottomBar_endExposed_propTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_offFocus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3bottomBar_endExposed_propTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4}
T8b949e# This is used to highlight the selected item when the widget does not have the focus.
Tff7b72selfTff7b72.Td2a8ff_highlight_offFocus Tff7b72= Tb4b4b4{Tff7b72NoneTb4b4b4:Te6edf3highlight_offFocusTb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72= Tff7b72None
T8b949e# A hook which is triggered when the selection changes.
Tff7b72selfTff7b72.Td2a8ffon_selection_change Tff7b72= Te6edf3on_selection_change
T8b949e# Initialization can be seen as a special case of selection change. This is interesting in combination with the hook.
Tff7b72selfTff7b72.Td2a8ff_initialization_is_selection_change Tff7b72= Te6edf3initialization_is_selection_change
T8b949e# 'MODIFIER_KEY' changes the behavior of the list box, so that it responds only to modified input. ('up' => 'ctrl up')
Tff7b72selfTff7b72.Td2a8ff_modifier_key Tff7b72= Te6edf3modifier_key
T8b949e# If the list item at the top is selected and you navigate further upwards, the input is normally not swallowed by the
T8b949e# list box, but passed on so that other widgets can interpret it. This may result in transferring the focus.
Tff7b72selfTff7b72.Td2a8ff_return_unused_navigation_input Tff7b72= Te6edf3return_unused_navigation_input
T8b949e# Is 'on_selection_change' triggered during the initialization?
Tff7b72if Te6edf3initialization_is_selection_change Tff7b72and Tb4b4b4(Te6edf3on_selection_change Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3on_selection_changeTb4b4b4(Tff7b72NoneTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Tff7b72__repr__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Tffd700{}Ta5d6ff(body=Ta5d6ff'Tffd700{}Ta5d6ff'Ta5d6ff, position=Ta5d6ff'Tffd700{}Ta5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ff__name__Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffget_bodyTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffrenderTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3focusTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3just_maxcol Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4,Tb4b4b4)
T8b949e# The size also includes the two bars, so subtract these.
Te6edf3modified_size Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T8b949e# cols
Te6edf3sizeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72- Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4)Tb4b4b4) T8b949e# rows
T8b949e# Evaluates which ends are visible and calculates how many list entries are hidden above/below. This is a modified form
T8b949e# of 'urwid.ListBox.ends_visible()'.
Te6edf3middleTb4b4b4, Te6edf3topTb4b4b4, Te6edf3bottom Tff7b72= Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffcalculate_visibleTb4b4b4(Te6edf3modified_sizeTb4b4b4, Te6edf3focusTff7b72=Te6edf3focusTb4b4b4)
Tff7b72if Te6edf3middle Tff7b72is Tff7b72NoneTb4b4b4: T8b949e# empty list box
Te6edf3top_is_visible Tff7b72= Tff7b72True
Te6edf3bottom_is_visible Tff7b72= Tff7b72True
Tff7b72elseTb4b4b4:
Te6edf3top_is_visible Tff7b72= Tff7b72False
Te6edf3bottom_is_visible Tff7b72= Tff7b72False
Te6edf3trim_topTb4b4b4, Te6edf3above Tff7b72= Te6edf3top
Te6edf3trim_bottomTb4b4b4, Te6edf3below Tff7b72= Te6edf3bottom
Tff7b72if Te6edf3trim_top Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3pos Tff7b72= Te6edf3aboveTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4[T79c0ff1Tb4b4b4] Tff7b72if Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3aboveTb4b4b4) Tff7b72!= T79c0ff0Tb4b4b4) Tff7b72else Te6edf3middleTb4b4b4[T79c0ff2Tb4b4b4]
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ff_bodyTff7b72.Td2a8ffget_prevTb4b4b4(Te6edf3posTb4b4b4) Tff7b72== Tb4b4b4(Tff7b72NoneTb4b4b4,Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3top_is_visible Tff7b72= Tff7b72True
Tff7b72elseTb4b4b4:
Te6edf3covered_above Tff7b72= Te6edf3pos
Tff7b72elseTb4b4b4:
Te6edf3covered_above Tff7b72= Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3trim_bottom Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3row_offsetTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3posTb4b4b4, Te6edf3rowsTb4b4b4, Te6edf3_ Tff7b72= Te6edf3middle
Te6edf3row_offset Tff7b72+Tff7b72= Te6edf3rows T8b949e# Include the selected position.
Tff7b72for Te6edf3_Tb4b4b4, Te6edf3posTb4b4b4, Te6edf3rows Tff7b72in Te6edf3belowTb4b4b4: T8b949e# 'pos' is overridden
Te6edf3row_offset Tff7b72+Tff7b72= Te6edf3rows
Tff7b72if Tb4b4b4(Te6edf3row_offset Tff7b72< Te6edf3modified_sizeTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4) Tff7b72or Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ff_bodyTff7b72.Td2a8ffget_nextTb4b4b4(Te6edf3posTb4b4b4) Tff7b72== Tb4b4b4(Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3bottom_is_visible Tff7b72= Tff7b72True
Tff7b72elseTb4b4b4:
Te6edf3covered_below Tff7b72= Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3pos
Tff7b72elseTb4b4b4:
Te6edf3covered_below Tff7b72= Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)
T8b949e# Changes the appearance of the bar at the top depending on whether the first list item is visible and the widget has
T8b949e# the focus.
Tff7b72if Te6edf3top_is_visibleTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8fforiginal_widgetTff7b72.Td2a8ffset_textTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_markupTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_focus
Tff7b72if Te6edf3focus Tff7b72else Tff7b72selfTff7b72.Td2a8ff_topBar_endExposed_offFocusTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8fforiginal_widgetTff7b72.Td2a8ffset_textTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_markupTff7b72.Td2a8ffformatTb4b4b4(Te6edf3covered_aboveTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_focus
Tff7b72if Te6edf3focus Tff7b72else Tff7b72selfTff7b72.Td2a8ff_topBar_endCovered_offFocusTb4b4b4)
T8b949e# Changes the appearance of the bar at the bottom depending on whether the last list item is visible and the widget
T8b949e# has the focus.
Tff7b72if Te6edf3bottom_is_visibleTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8fforiginal_widgetTff7b72.Td2a8ffset_textTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_markupTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_focus
Tff7b72if Te6edf3focus Tff7b72else Tff7b72selfTff7b72.Td2a8ff_bottomBar_endExposed_offFocusTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8fforiginal_widgetTff7b72.Td2a8ffset_textTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_markupTff7b72.Td2a8ffformatTb4b4b4(Te6edf3covered_belowTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_focus
Tff7b72if Te6edf3focus Tff7b72else Tff7b72selfTff7b72.Td2a8ff_bottomBar_endCovered_offFocusTb4b4b4)
T8b949e# The highlighting in urwid is bound to the focus. This means that the selected item is only distinguishable as long as
T8b949e# the widget has the focus. To compensate this, the color scheme of the selected item is otherwiese temporarily changed.
Tff7b72if Te6edf3focus Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# Resets the appearance of the selected item to its original value.
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocusTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_mapTb4b4b4)
Tff7b72elif Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_highlight_offFocus Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4) \
Tff7b72and Tff7b72not Te6edf3focus \
Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72or Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72is Tff7b72NoneTb4b4b4)Tb4b4b4) \
Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffbody_is_emptyTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e# Store the 'attr_map' of the selected item and then change it to accomplish off focus highlighting.
Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72= Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocusTff7b72.Td2a8ffget_attr_mapTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocusTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_highlight_offFocusTb4b4b4)
T8b949e# Store the last focus to do/undo the off focus highlighting only if the focus has really changed and not if the
T8b949e# widget is re-rendered because the terminal size has changed or similar.
Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72= Te6edf3focus
Tff7b72selfTff7b72.Td2a8fftop_is_visible Tff7b72= Te6edf3top_is_visible
Tff7b72selfTff7b72.Td2a8ffbottom_is_visible Tff7b72= Te6edf3bottom_is_visible
Tff7b72return Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffrenderTb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3focusTff7b72=Te6edf3focusTb4b4b4)
Tff7b72def Td2a8ffkeypressTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
Te6edf3just_maxcol Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4,Tb4b4b4)
T8b949e# The size also includes the two bars, so subtract these.
Te6edf3modified_size Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T8b949e# cols
Te6edf3sizeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72- Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4)Tb4b4b4) T8b949e# rows
T8b949e# Store the focus position before passing the keystroke to the contained list box. That way, it can be compared with the
T8b949e# position after the input is processed. If the list box body is empty, store None.
Te6edf3focus_position_before_input Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
T8b949e# A keystroke is changed to a modified one ('up' => 'ctrl up'). This prevents the widget from responding when the arrows
T8b949e# keys are used to navigate between widgets. That way it can be used in a 'urwid.Pile' or similar.
Tff7b72if Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffupTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffupTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffdownTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffdownTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffpage upTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffpage upTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffpage downTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffpage downTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffhomeTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e# Check if the first list item is already selected.
Tff7b72if Tb4b4b4(Te6edf3focus_position_before_input Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4) Tff7b72and Tb4b4b4(Te6edf3focus_position_before_input Tff7b72!= T79c0ff0Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffselect_first_itemTb4b4b4(Tb4b4b4)
Te6edf3key Tff7b72= Tff7b72None
Tff7b72elif Tff7b72not Tff7b72selfTff7b72.Td2a8ff_return_unused_navigation_inputTb4b4b4:
Te6edf3key Tff7b72= Tff7b72None
Tff7b72elif Te6edf3key Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffendTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e# Check if the last list item is already selected.
Tff7b72if Tb4b4b4(Te6edf3focus_position_before_input Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4) Tff7b72and Tb4b4b4(Te6edf3focus_position_before_input Tff7b72!= Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffselect_last_itemTb4b4b4(Tb4b4b4)
Te6edf3key Tff7b72= Tff7b72None
Tff7b72elif Tff7b72not Tff7b72selfTff7b72.Td2a8ff_return_unused_navigation_inputTb4b4b4:
Te6edf3key Tff7b72= Tff7b72None
Tff7b72elif Te6edf3key Tff7b72not Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffupTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdownTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpage upTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpage downTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffhomeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffendTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffkeypressTb4b4b4(Te6edf3modified_sizeTb4b4b4, Te6edf3keyTb4b4b4)
Te6edf3focus_position_after_input Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
T8b949e# If the focus position has changed, execute the hook (if existing).
Tff7b72if Tb4b4b4(Te6edf3focus_position_before_input Tff7b72!= Te6edf3focus_position_after_inputTb4b4b4) Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_selection_change Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_selection_changeTb4b4b4(Te6edf3focus_position_before_inputTb4b4b4,
Te6edf3focus_position_after_inputTb4b4b4)
Tff7b72return Te6edf3key
Tff7b72def Td2a8ffmouse_eventTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3eventTb4b4b4, Te6edf3buttonTb4b4b4, Te6edf3colTb4b4b4, Te6edf3rowTb4b4b4, Te6edf3focusTb4b4b4)Tb4b4b4:
Te6edf3just_maxcol Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4,Tb4b4b4)
Te6edf3topBar_rows Tff7b72= Tff7b72selfTff7b72.Td2a8ff_top_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4)
Te6edf3bottomBar_rows Tff7b72= Tff7b72selfTff7b72.Td2a8ff_bottom_barTff7b72.Td2a8ffrowsTb4b4b4(Te6edf3just_maxcolTb4b4b4)
T8b949e# The size also includes the two bars, so subtract these.
Te6edf3modified_size Tff7b72= Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T8b949e# cols
Te6edf3sizeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72- Te6edf3topBar_rows Tff7b72- Te6edf3bottomBar_rowsTb4b4b4) T8b949e# rows
Te6edf3was_handeled Tff7b72= Tff7b72False
T8b949e# An event is changed to a modified one ('mouse press' => 'ctrl mouse press'). This prevents the widget from responding
T8b949e# when mouse buttons are also used to navigate between widgets.
Tff7b72if Te6edf3event Tff7b72== Tff7b72selfTff7b72.Td2a8ff_modifier_keyTff7b72.Td2a8ffprepend_toTb4b4b4(Ta5d6ff"Ta5d6ffmouse pressTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e# Store the focus position before passing the input to the contained list box. That way, it can be compared with the
T8b949e# position after the input is processed. If the list box body is empty, store None.
Te6edf3focus_position_before_input Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
T8b949e# Also remember the currently selected item itself. A button 1 press makes the contained list box move the focus, but
T8b949e# the off focus highlighting is only (un)done during 'render()' while the widget has the focus. When the selection is
T8b949e# changed by mouse while the widget is unfocused, the highlight would otherwise stay stuck on the previous item.
Te6edf3item_before_input Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_itemTb4b4b4(Tb4b4b4)
T8b949e# left mouse button, if not top bar or bottom bar.
Tff7b72if Tb4b4b4(Te6edf3button Tff7b72== T79c0ff1.0Tb4b4b4) Tff7b72and Tb4b4b4(Te6edf3topBar_rows Tff7b72<Tff7b72= Te6edf3row Tff7b72< Tb4b4b4(Te6edf3sizeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72- Te6edf3bottomBar_rowsTb4b4b4)Tb4b4b4)Tb4b4b4:
T8b949e# Because 'row' includes the top bar, the offset must be substracted before passing it to the contained list box.
Te6edf3result Tff7b72= Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffmouse_eventTb4b4b4(Te6edf3modified_sizeTb4b4b4, Te6edf3eventTb4b4b4, Te6edf3buttonTb4b4b4, Te6edf3colTb4b4b4, Tb4b4b4(Te6edf3row Tff7b72- Te6edf3topBar_rowsTb4b4b4)Tb4b4b4, Te6edf3focusTb4b4b4)
Te6edf3was_handeled Tff7b72= Te6edf3result Tff7b72if Tff7b72selfTff7b72.Td2a8ff_return_unused_navigation_input Tff7b72else Tff7b72True
T8b949e# mousewheel up
Tff7b72elif Te6edf3button Tff7b72== T79c0ff4.0Tb4b4b4:
T8b949e# was_handeled = self._pass_key_to_contained_listbox(modified_size, "page up")
Te6edf3was_handeled Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffupTa5d6ff"Tb4b4b4)
T8b949e# mousewheel down
Tff7b72elif Te6edf3button Tff7b72== T79c0ff5.0Tb4b4b4:
T8b949e# was_handeled = self._pass_key_to_contained_listbox(modified_size, "page down")
Te6edf3was_handeled Tff7b72= Tff7b72selfTff7b72.Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Te6edf3modified_sizeTb4b4b4, Ta5d6ff"Ta5d6ffdownTa5d6ff"Tb4b4b4)
Te6edf3focus_position_after_input Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3focus_position_before_input Tff7b72!= Te6edf3focus_position_after_inputTb4b4b4:
T8b949e# The mouse moved the selection. If off focus highlighting is currently applied (the widget is unfocused), restore
T8b949e# the previously selected item and clear the stored state, so the next 'render()' re-applies the highlight to the
T8b949e# newly selected item instead of leaving it stuck on the old one.
Tff7b72if Tb4b4b4(Tff7b72not Tff7b72selfTff7b72.Td2a8ff_last_focus_stateTb4b4b4) Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4) Tff7b72and Tb4b4b4(Te6edf3item_before_input Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3item_before_inputTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_mapTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72= Tff7b72None
T8b949e# If the focus position has changed, execute the hook (if existing).
Tff7b72if Tff7b72selfTff7b72.Td2a8ffon_selection_change Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_selection_changeTb4b4b4(Te6edf3focus_position_before_inputTb4b4b4,
Te6edf3focus_position_after_inputTb4b4b4)
Tff7b72return Te6edf3was_handeled
T8b949e# Pass the keystroke to the original widget. If it is not used, evaluate the corresponding variable to decide if it gets
T8b949e# swallowed or not.
Tff7b72def Td2a8ff_pass_key_to_contained_listboxTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
Te6edf3result Tff7b72= Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffkeypressTb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3keyTb4b4b4)
Tff7b72return Te6edf3result Tff7b72if Tff7b72selfTff7b72.Td2a8ff_return_unused_navigation_input Tff7b72else Tff7b72None
Tff7b72def Td2a8ffget_bodyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffbody
Tff7b72def Td2a8ffbody_lenTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_bodyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffrearmost_positionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_bodyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72- T79c0ff1 T8b949e# last valid index
Tff7b72def Td2a8ffbody_is_emptyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffbody_lenTb4b4b4(Tb4b4b4) Tff7b72== T79c0ff0
Tff7b72def Td2a8ffposition_is_validTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3positionTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3position Tff7b72< Tff7b72selfTff7b72.Td2a8ffbody_lenTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72and Tb4b4b4(Te6edf3position Tff7b72>Tff7b72= T79c0ff0Tb4b4b4)
T8b949e# If the passed position is valid, it is returned. Otherwise, the nearest valid position is returned. This ensures that
T8b949e# positions which are out of range do not result in an error.
Tff7b72def Td2a8ff_get_nearest_valid_positionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3positionTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffbody_is_emptyTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3pos_type Tff7b72= Tffa657typeTb4b4b4(Te6edf3positionTb4b4b4)
Tff7b72if Te6edf3pos_type Tff7b72== Tffa657intTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffposition_is_validTb4b4b4(Te6edf3positionTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3position
Tff7b72elif Te6edf3position Tff7b72< T79c0ff0Tb4b4b4:
Tff7b72return T79c0ff0
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3pos_type Tff7b72== Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ffPOSITIONTb4b4b4:
Tff7b72if Te6edf3position Tff7b72== Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ffPOSITIONTff7b72.Td2a8ffLASTTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3position Tff7b72== Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ffPOSITIONTff7b72.Td2a8ffMIDDLETb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffbody_lenTb4b4b4(Tb4b4b4) Tff7b72/Tff7b72/ T79c0ff2
Tff7b72elif Te6edf3position Tff7b72== Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ffPOSITIONTff7b72.Td2a8ffRANDOMTb4b4b4:
Tff7b72return Te6edf3randomTff7b72.Td2a8ffrandintTb4b4b4(T79c0ff0Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ff_VALUE_ERR_MSGTff7b72.Td2a8ffformatTb4b4b4(Te6edf3positionTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Tff7b72selfTff7b72.Td2a8ff__class__Tff7b72.Td2a8ff_TYPE_ERR_MSGTff7b72.Td2a8ffformatTb4b4b4(Ta5d6ff"Ta5d6ff<class Ta5d6ff'Ta5d6ffintTa5d6ff'Ta5d6ff> or <enum Ta5d6ff'Ta5d6ffIndicativeListBox.POSITIONTa5d6ff'Ta5d6ff>Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ff'Ta5d6ffpositionTa5d6ff'Ta5d6ff"Tb4b4b4,
Te6edf3pos_typeTb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffget_itemTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3positionTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffposition_is_validTb4b4b4(Te6edf3positionTb4b4b4)Tb4b4b4:
Te6edf3body Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_bodyTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3bodyTb4b4b4[Te6edf3positionTb4b4b4]
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffget_first_itemTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffget_itemTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72def Td2a8ffget_last_itemTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffget_itemTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffget_selected_itemTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocus
Tff7b72def Td2a8ffget_selected_positionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocus_position Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffbody_is_emptyTb4b4b4(Tb4b4b4) Tff7b72else Tff7b72None
Tff7b72def Td2a8fffirst_item_is_selectedTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4) Tff7b72== T79c0ff0
Tff7b72def Td2a8fflast_item_is_selectedTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4) Tff7b72== Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_reset_highlightingTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Resets the appearance of the selected item to its original value, if off focus highlighting is active.
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8fffocusTff7b72.Td2a8ffset_attr_mapTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_original_item_attr_mapTb4b4b4)
T8b949e# The next time the widget is rendered, the highlighting is redone.
Tff7b72selfTff7b72.Td2a8ff_original_item_attr_map Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_last_focus_state Tff7b72= Tff7b72None
Tff7b72def Td2a8ffset_bodyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bodyTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3alternative_positionTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3focus_position_before_change Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reset_highlightingTb4b4b4(Tb4b4b4)
T8b949e# Wrap each item in an 'urwid.AttrMap', if not already done.
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffbodyTb4b4b4[Tb4b4b4:Tb4b4b4] Tff7b72= Tb4b4b4[Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4(Te6edf3itemTb4b4b4, Tff7b72NoneTb4b4b4) Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Te6edf3urwidTff7b72.Td2a8ffAttrMapTb4b4b4) Tff7b72else Te6edf3item
Tff7b72for Te6edf3item Tff7b72in Te6edf3bodyTb4b4b4]
T8b949e# Normally it is tried to hold the focus position. If this is not desired, a position can be passed.
Tff7b72if Te6edf3alternative_position Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3nearest_valid_position Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_nearest_valid_positionTb4b4b4(Te6edf3alternative_positionTb4b4b4)
Tff7b72if Te6edf3nearest_valid_position Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
T8b949e# Because the widget has been re-rendered, the off focus highlighted item must be restored to its original state.
Tff7b72selfTff7b72.Td2a8ff_reset_highlightingTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffset_focusTb4b4b4(Te6edf3nearest_valid_positionTb4b4b4)
T8b949e# If an initialization is considered a selection change, execute the hook (if existing).
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_initialization_is_selection_change Tff7b72and Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_selection_change Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_selection_changeTb4b4b4(Te6edf3focus_position_before_changeTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffselect_itemTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3positionTb4b4b4)Tb4b4b4:
Te6edf3focus_position_before_change Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
Te6edf3nearest_valid_position Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_nearest_valid_positionTb4b4b4(Te6edf3positionTb4b4b4)
T8b949e# Focus the new position, if possible and not already focused.
Tff7b72if Tb4b4b4(Te6edf3nearest_valid_position Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4) Tff7b72and Tb4b4b4(Te6edf3nearest_valid_position Tff7b72!= Te6edf3focus_position_before_changeTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_reset_highlightingTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_listboxTff7b72.Td2a8ffset_focusTb4b4b4(Te6edf3nearest_valid_positionTb4b4b4)
T8b949e# Execute the hook (if existing).
Tff7b72if Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_selection_change Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_selection_changeTb4b4b4(Te6edf3focus_position_before_changeTb4b4b4,
Te6edf3nearest_valid_positionTb4b4b4)
Tff7b72def Td2a8ffselect_first_itemTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffselect_itemTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72def Td2a8ffselect_last_itemTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffselect_itemTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrearmost_positionTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffdelete_positionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3positionTb4b4b4)Tb4b4b4:
T8b949e# The saved properties get reseted, just in case that the appearance of the items differs.
Tff7b72selfTff7b72.Td2a8ff_reset_highlightingTb4b4b4(Tb4b4b4)
Te6edf3body Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_bodyTb4b4b4(Tb4b4b4)
Tff7b72del Te6edf3bodyTb4b4b4[Te6edf3positionTb4b4b4]
Tff7b72def Td2a8ffdelete_selected_positionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pos Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_selected_positionTb4b4b4(Tb4b4b4)
T8b949e# If the list body is not empty, delete the selected item.
Tff7b72if Te6edf3pos Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdelete_positionTb4b4b4(Te6edf3posTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────